#include <linux/proc_fs.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <linux/string.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqreturn.h>
#include <linux/module.h>
#include <linux/device.h>


static int major;
static unsigned char buff[100];
static struct class *sr501_class;

/*sr501 args*/
//unsigned int sr501_gpio = 129;    	//对照原理图       蜂鸣器     GPIO5_IO1
//unsigned int key_gpio = 18;     	//对照原理图       按键      GPIO1_IO18
//unsigned int led_gpio = 3;      	//对照原理图       led     GPIO1_IO3

unsigned int sr501_gpio = 2;        //对照原理图       sr501    GPIO1_IO2
int sr501_irq;   //存储中断号


static irqreturn_t sr501_handle(int irqs, void *dev_id)
{
	int value;
	/*读取sr501的值*/
	value = gpio_get_value(sr501_gpio);
	printk("this is sr501_handle, irq = %d\n",irqs);
	printk("read sr501 = %d, %s\n", value, value == 1 ? "people" : "people go out");

	return IRQ_HANDLED;
}

static int sr501_open (struct inode *node, struct file *filp)
{
	printk("sr501_open\n");
	printk("%s %s %d\n",__FILE__, __FUNCTION__, __LINE__);

	return 0;
}

static ssize_t sr501_read (struct file *filp, char *buf, size_t size, loff_t *offset)
{
	int err;

	printk("sr501_drv_read\n");

	/*read sr501_gpio value*/
	buff[0] = gpio_get_value(sr501_gpio);
	
	err = copy_to_user(buf, buff, 1);

	//返回什么不重要，也可以直接返回gpio的值，但是最好还是按照驱动程序模式来写，使用copy_to_user
	return buff[0];  
}

static int sr501_release (struct inode *node, struct file *filp)
{
	printk("sr501_release\n");
	return 0;
}

/*1.定义 file_operations 结构体*/
static const struct file_operations sr501_fops = {
    .owner 		= THIS_MODULE,
	.read		= sr501_read,
	.open		= sr501_open,
	.release    = sr501_release,
};


/*3.入口函数*/
static int sr501_init(void)
{
	int err;
	/************* 1.注册设备，返回设备号 ************/
	major = register_chrdev(0,"sr501_drv",&sr501_fops);

	/*2.在内核中创建设备*/
	sr501_class = class_create(THIS_MODULE, "sr501_class");
	if (IS_ERR(sr501_class)) {
		printk("sr501 class create failed!\n");
	}

	/*3.在/dev下面创建设备节点*/
	device_create(sr501_class, NULL, MKDEV(major, 0), NULL, "sr501_drv");

	/************* 4.初始化sr501引脚 ************/
	/*申请sr501引脚*/
//	err = gpio_request(sr501_gpio, "sr501_gpio");
//	if(err < 0){
//		printk("sr501 gpio request failed!\n");
//		return -ENODEV;
//	}
//	gpio_direction_input(sr501_gpio);

	/************* 5.sr501引脚申请中断 ************/
	sr501_irq = gpio_to_irq(sr501_gpio);
	printk("request irq = %d\n", sr501_irq);
	/*上升沿和下降沿都触发，上升沿-有人，下降沿-人走了*/
	err = request_irq(sr501_irq, sr501_handle, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 
					  "sr501_irq", NULL);  // 
	if(err != 0){
		printk("request irq error!\n");
	}
	
	return 0;
}

/*4.退出函数*/
static void sr501_exit(void)
{
	/*释放sr501_gpio引脚中断*/
	free_irq(sr501_irq, NULL);

	//销毁设备
	device_destroy(sr501_class, MKDEV(major, 0));
	
	//删除设备类
	class_destroy(sr501_class);

	//卸载设备
	unregister_chrdev(major,"sr501_fops");

//	gpio_free(sr501_gpio);

	printk("sr501_exit\n");

}

module_init(sr501_init);
module_exit(sr501_exit);
MODULE_LICENSE("GPL");

